
$RedGravity_JumpTimeoutMs = 200;
$RedGravity_JumpGroundHeight = 2;
$RedGravity_GravityGroundHeight = 30;
$RedGravity_GroundMask = $TypeMasks::TerrainObjectType | $TypeMasks::FxBrickObjectType | $TypeMasks::StaticObjectType;

if(!isFunction(WheeledVehicleData, onTrigger)) eval("function WheeledVehicleData::onTrigger(){}");
if(!isFunction(FlyingVehicleData , onTrigger)) eval("function FlyingVehicleData ::onTrigger(){}");
if(!isFunction(WheeledVehicleData, onAdd    )) eval("function WheeledVehicleData::onAdd    (){}");
if(!isFunction(FlyingVehicleData , onAdd    )) eval("function FlyingVehicleData ::onAdd    (){}");

package RedBase_Gravity {
	function WheeledVehicleData::onTrigger(%data, %vehicle, %trig, %val) {
		if(%trig==2 && %val && %data.jumpImpulse) RedGravity_Jump(%data, %vehicle);
		parent::onTrigger(%data, %vehicle, %trig, %val);
	}
	function FlyingVehicleData::onTrigger(%data, %vehicle, %trig, %val) {
		if(%trig==2 && %val && %data.jumpImpulse) RedGravity_Jump(%data, %vehicle);
		parent::onTrigger(%data, %vehicle, %trig, %val);
	}
	
	function WheeledVehicleData::onAdd(%data, %vehicle) {
		parent::onAdd(%data, %vehicle);
		if(%data.isGravityVehicle) RedGravity_Loop(%vehicle);
	}
	function FlyingVehicleData::onAdd(%data, %vehicle) {
		parent::onAdd(%data, %vehicle);
		if(%data.isGravityVehicle) RedGravity_Loop(%vehicle);
	}
};
activatePackage(RedBase_Gravity);

function RedGravity_IsOnGround(%vehicle) {
	%pos = %vehicle.getPosition();
	%vec = vectorScale(%vehicle.getUpVector(), -$RedGravity_JumpGroundHeight);
	%ray = containerRaycast(%pos, vectorAdd(%pos, %vec), $RedGravity_GroundMask, %vehicle);
	%hit = getWord(%ray, 0);
	return isObject(%hit);
}
function RedGravity_Jump(%data, %vehicle) {
	if(getSimTime() < $RedGravity_JumpTimeoutMs + %vehicle.jumpTimeMs) return;
	if(!RedGravity_IsOnGround(%vehicle)) return;
	%vehicle.applyImpulse(
		%vehicle.getPosition(),
		vectorScale(%vehicle.getUpVector(), %data.jumpImpulse)
	);
	%vehicle.lastJumpTime = getSimTime();
}
function RedGravity_Loop(%vehicle) {
	if(!isObject(%vehicle)) return;
	
	%time = getSimTime();
	%dtime = %time - %vehicle.RedGravity_LastUpdateTime;
	%vehicle.RedGravity_LastUpdateTime = %time;
	
	if(%dtime < 100 && %dtime>0) {
		%len = 5;
		%pos = %vehicle.getPosition();
		%vec = vectorScale(%vehicle.getUpVector(), -$RedGravity_GravityGroundHeight);
		%ray = containerRaycast(%pos, vectorAdd(%pos, %vec), $RedGravity_GroundMask, %vehicle);
		
		if(%ray) {
			%normal = getWords(%ray, 4, 6);
			%gravity = 20; //TU/s/s acceleration of gravity as measured ingame
			%vel = vectorAdd(
				"0 0 " @ %gravity*%dtime/1000, // cancel normal gravity
				vectorScale(%normal, -%gravity*%dtime/1000) // stick to wall
			);
			%vehicle.setVelocity(vectorAdd(%vehicle.getVelocity(), %vel));
		}
	}
	
	schedule(16, 0, RedGravity_Loop, %vehicle);
}
